package javatunes;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;

/** 
 * a class supposedly to read an itunes db file and get some songs
 * 
 * Look at http://ipodlinux.org/ITunesDB#iTunesDB_file for details
 * of the way the file is made up
 *
 */
public class itunesdbreader {

	public static final String IPODDRIVE="G:\\";
	public static final String DBLOCATION=IPODDRIVE+"iPod_Control\\iTunes\\iTunesDB";
	sebpac p;
	
	public ArrayList<mhit> alltracks;
	
	int headersize;
	
	/** 
	 * it appears that numbers are stored little endian, so use g4i instead of g4 etc
	 * @throws Exception
	 */
	public itunesdbreader() throws Exception {
		init();
		alltracks=getalltracks();
	}
	
	private ArrayList<mhit> getalltracks() {
		ArrayList<mhit> alltracks=new ArrayList<mhit>();
		String lastheader="";
		int howmanysongs=0;
		while (!lastheader.equals("mhlt")) {
			lastheader=p.gnstr(4);
			if (lastheader.equals("mhlt")) {
				p.pos+=4;
				howmanysongs=p.g4i();
			}
			else {
				p.pos-=4;
				read4byteheaderandskip();
			}
		}
		
		lastheader=p.gnstr(4);
		for (int i=0; i<howmanysongs; i++) {
			int headersize=p.g4i(); 
			p.pos+=4; // skip total size
			int numberofstrings=p.g4i(); // at index 16
			p.pos+=44-16; // at index 44;
			int tracknumber=p.g4i(); // at index 48
			p.pos+=headersize-48; // skip previous 48 bytes and go to end of mhit header
			alltracks.add(gettrackitem(numberofstrings,tracknumber));
			
			// find next mhit track item
			while (!(lastheader=p.gnstr(4)).equals("mhit")) {}
			
		}
		//System.out.println("howmanysongs: " + howmanysongs);
		return alltracks;
	}
	
	int lasttype=0;
	
	private mhit gettrackitem(int numberofstrings, int tracknumber) {
		String[] strs=new String[15];
		for (int i=0;i<numberofstrings;i++) {
			mhod temp;
			if (p.gnstr(4).equals("mhod")){
				temp=new mhod(p);
				if (temp.type<15) {
					strs[temp.type-1]=temp.str;
				}
			}
			
		}
		return new mhit(strs,tracknumber);
	}
	
	private String read4byteheaderandskip() {
		String header=p.gnstr(4);
		headersize=p.g4i();
		p.pos+=headersize-8;
		return header;
	}
	
	private void init() throws Exception {
		p=new sebpac(getBytesFromFile(new File(DBLOCATION)));
		p.pos=0;
	}
	
	public static ArrayList<mhit> search(ArrayList<mhit> previousresults, Object[] artists, Object[] albums, Object[] titles, Object[] genres) {
		if (genres==null || genres.length==0 || (genres.length>0 && genres[0].equals("(All)")) || (genres.length==1 && genres[0].equals(""))) genres=null;
		if (artists==null || artists.length==0 || (artists.length>0 && artists[0].equals("(All)")) || (artists.length==1 && artists[0].equals(""))) artists=null;
		if (albums==null || albums.length==0 || (albums.length>0 && albums[0].equals("(All)")) || (albums.length==1 && albums[0].equals(""))) albums=null;
		if (titles==null || titles.length==0 || (titles.length>0 && titles[0].equals("(All)")) || (titles.length==1 && titles[0].equals(""))) titles=null;
		
		ArrayList<mhit> newresults=new ArrayList<mhit>();
		if (artists==null && albums==null && titles==null && genres==null) return previousresults;
		mhit current;
		for (int i=0;i<previousresults.size();i++) {
			current=previousresults.get(i);
			if (current.artist.length()==0 && current.album.length()==0 && current.title.length()==0 && current.genre.length()==0) continue;
			int gotgenre=0;
			int gotartist=0;
			int gotalbum=0;
			int gottitle=0;
			if (genres!=null) for (Object genre:genres) gotgenre+=(current.genre.toLowerCase().contains(((String)genre).toLowerCase())||((String)genre).length()==0)?1:0;
			if (artists!=null) for (Object artist:artists) gotartist+=(current.artist.toLowerCase().contains(((String)artist).toLowerCase())||((String)artist).length()==0)?1:0;
			if (albums!=null) for (Object album:albums) gotalbum+=(current.album.toLowerCase().contains(((String)album).toLowerCase())||((String)album).length()==0)?1:0;
			if (titles!=null) for (Object title:titles) gottitle+=(current.title.toLowerCase().contains(((String)title).toLowerCase())||((String)title).length()==0)?1:0;			
			
			if ((genres==null || gotgenre>0) && (artists==null || gotartist>0) && (albums==null || gotalbum>0) && (titles==null || gottitle>0)) newresults.add(current);			
		}
		return newresults;
	}
	
	private static byte[] getBytesFromFile(File file) throws Exception {
        InputStream is = new FileInputStream(file);
    
        long length = file.length();
    
        if (length > Integer.MAX_VALUE) {
        	System.out.println("file is too large...");
        	System.exit(1);
        }
    
        byte[] bytes = new byte[(int)length];
    
        int offset = 0;
        int numRead = 0;
        while (offset < bytes.length
               && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
            offset += numRead;
        }
    
        if (offset < bytes.length) {
            System.out.println("broke!");
            System.exit(1);
        }
    
        is.close();
        return bytes;
    }
	
}
